import json
import os
import time

import execjs
import requests


class Music:
    def __init__(self):
        self.headers = {
            "authority": "u6.y.qq.com",
            "accept": "application/json",
            "accept-language": "zh-CN,zh;q=0.9",
            "cache-control": "no-cache",
            "content-type": "application/x-www-form-urlencoded",
            "origin": "https://y.qq.com",
            "pragma": "no-cache",
            "referer": "https://y.qq.com/",
            "sec-fetch-dest": "empty",
            "sec-fetch-mode": "cors",
            "sec-fetch-site": "same-site",
            "cookie": "pgv_pvid=2784046238; fqm_pvqid=f0fc0b1e-e065-416d-9644-c5b35cf24254; fqm_sessionid=5d67103c-06b5-489b-a6b8-ecb20e681d12; pgv_info=ssid=s7420048000; ts_uid=1642784362; _qpsvr_localtk=0.3279057586404921; yqq_stat=0; ptui_loginuin=1145087558; RK=0h0Rhu2DVe; ptcz=fa8e21d257db35d57edea169a0c70b62ebb9342a444baf36dbc94e274cdfaa3e; login_type=1; psrf_qqrefresh_token=7C78C36140E079252DF0F83C1F033BA4; wxunionid=; euin=oK6P7KnF7i4kNn**; uin=1145087558; tmeLoginType=2; psrf_qqopenid=6C09A7EC1BBCADE5FD3EF85423492928; psrf_musickey_createtime=1711532336; psrf_qqunionid=4224849A22B8A6625A52DE84BF5DC3C7; psrf_qqaccess_token=F1C2EAFBF59C3EA8B7B447B6A8451DE1; wxrefresh_token=; psrf_access_token_expiresAt=1719308336; wxopenid=; qqmusic_key=Q_H_L_63k3N-jAsun0gMVDufWasxNUkxnsd19Mh8dfVroDic9WecWMioYZInEPcmLa1WwAZCkzBvMIAug; music_ignore_pskey=202306271436Hn@vBj; qm_keyst=Q_H_L_63k3N-jAsun0gMVDufWasxNUkxnsd19Mh8dfVroDic9WecWMioYZInEPcmLa1WwAZCkzBvMIAug; ts_last=y.qq.com/n/ryqq/search",
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"
        }
        self.cookie = {
            "pgv_pvid": "2784046238",
            "fqm_pvqid": "f0fc0b1e-e065-416d-9644-c5b35cf24254",
            "fqm_sessionid": "5d67103c-06b5-489b-a6b8-ecb20e681d12",
            "pgv_info": "ssid=s7420048000",
            "ts_uid": "1642784362",
            "_qpsvr_localtk": "0.3279057586404921",
            "yqq_stat": "0",
            "ts_last": "y.qq.com/n/ryqq/search",
            "ptui_loginuin": "1145087558",
            "RK": "0h0Rhu2DVe",
            "ptcz": "fa8e21d257db35d57edea169a0c70b62ebb9342a444baf36dbc94e274cdfaa3e",
            "login_type": "1",
            "psrf_qqrefresh_token": "7C78C36140E079252DF0F83C1F033BA4",
            "wxunionid": "",
            "euin": "oK6P7KnF7i4kNn**",
            "uin": "1145087558",
            "tmeLoginType": "2",
            "psrf_qqopenid": "6C09A7EC1BBCADE5FD3EF85423492928",
            "psrf_musickey_createtime": "1711532336",
            "psrf_qqunionid": "4224849A22B8A6625A52DE84BF5DC3C7",
            "psrf_qqaccess_token": "F1C2EAFBF59C3EA8B7B447B6A8451DE1",
            "wxrefresh_token": "",
            "psrf_access_token_expiresAt": "1719308336",
            "wxopenid": "",
            "qqmusic_key": "Q_H_L_63k3N-jAsun0gMVDufWasxNUkxnsd19Mh8dfVroDic9WecWMioYZInEPcmLa1WwAZCkzBvMIAug",
            "music_ignore_pskey": "202306271436Hn^@vBj",
            "qm_keyst": "Q_H_L_63k3N-jAsun0gMVDufWasxNUkxnsd19Mh8dfVroDic9WecWMioYZInEPcmLa1WwAZCkzBvMIAug,"
        }
        self.js = execjs.compile(open('qq音乐.js', encoding='utf-8').read())
        self.song_list = []

    def get_list(self, page, singer_name):
        url = "https://u6.y.qq.com/cgi-bin/musics.fcg"
        data = {
            "comm": {
                "cv": 4747474,
                "ct": 24,
                "format": "json",
                "inCharset": "utf-8",
                "outCharset": "utf-8",
                "notice": 0,
                "platform": "yqq.json",
                "needNewCode": 1,
                "uin": 1145087558,
                "g_tk_new_20200303": 1468898966,
                "g_tk": 1468898966
            },
            "req_1": {
                "method": "DoSearchForQQMusicDesktop",
                "module": "music.search.SearchCgiService",
                "param": {
                    "remoteplace": "yqq.yqq.yqq",
                    "searchid": "59933507016538488",
                    "search_type": 0,
                    "query": singer_name,
                    "page_num": page,
                    "num_per_page": 10
                }
            }
        }

        data_str = str(json.dumps(data, ensure_ascii=False, separators=(",", ":")))
        # print(data_str)
        sign = self.js.call('get_data', data_str)
        params = {
            "_": str(int(time.time() * 1000)),
            "sign": sign
        }
        # print(params)
        response = requests.post(url, headers=self.headers, params=params,
                                 data=data_str.encode())

        # print(response)
        res = response.json()
        # 获取歌曲列表
        result = res['req_1']['data']['body']['song']['list']
        count = 1 + (page - 1) * 10
        for data in result:
            file_name = ""
            is_vip = data["pay"]["pay_play"] == 1
            if is_vip:
                file_name = "RS02" + data["vs"][0] + ".mp3"

            mark = "VIP歌曲 " if is_vip else "非VIP歌曲 "
            print("编号" + str(count) + ": ", data['name'], mark)
            count += 1
            item = dict()
            item["song_name"] = data['name']
            item["mid"] = data['mid']
            item["singer_name"] = singer_name
            item["file_name"] = file_name
            item["mark"] = mark
            self.song_list.append(item)
            # self.down(data["mid"], data['name'], singer_name, file_name, is_vip)

    def down(self, item):
        url = "https://u6.y.qq.com/cgi-bin/musics.fcg"
        mid = item['mid']
        data = {
            "comm": {
                "cv": 4747474,
                "ct": 24,
                "format": "json",
                "inCharset": "utf-8",
                "outCharset": "utf-8",
                "notice": 0,
                "platform": "yqq.json",
                "needNewCode": 1,
                "uin": 1145087558,
                "g_tk_new_20200303": 1468898966,
                "g_tk": 1468898966
            },
            "req_1": {
                "module": "userInfo.VipQueryServer",
                "method": "SRFVipQuery_V2",
                "param": {
                    "uin_list": [
                        "1145087558"
                    ]
                }
            },
            "req_2": {
                "module": "userInfo.BaseUserInfoServer",
                "method": "get_user_baseinfo_v2",
                "param": {
                    "vec_uin": [
                        "1145087558"
                    ]
                }
            },
            "req_3": {
                "module": "music.lvz.VipIconUiShowSvr",
                "method": "GetVipIconUiV2",
                "param": {
                    "PID": 3
                }
            },
            "req_4": {
                "module": "vkey.GetVkeyServer",
                "method": "CgiGetVkey",
                "param": {
                    "guid": "3354595536",
                    "songmid": [
                        mid
                    ],
                    "songtype": [
                        0
                    ],
                    "uin": "1145087558",
                    "loginflag": 1,
                    "platform": "20"
                }
            },
            "req_5": {
                "module": "music.musicasset.SongFavRead",
                "method": "IsSongFanByMid",
                "param": {
                    "v_songMid": [
                        mid
                    ]
                }
            },
            "req_6": {
                "module": "music.musichallSong.PlayLyricInfo",
                "method": "GetPlayLyricInfo",
                "param": {
                    "songMID": mid,
                    "songID": 5106430
                }
            },
            "req_7": {
                "method": "GetCommentCount",
                "module": "music.globalComment.GlobalCommentRead",
                "param": {
                    "request_list": [
                        {
                            "biz_type": 1,
                            "biz_id": "469440301",
                            "biz_sub_type": 0
                        }
                    ]
                }
            },
            "req_8": {
                "module": "music.musichallAlbum.AlbumInfoServer",
                "method": "GetAlbumDetail",
                "param": {
                    "albumMid": "000QgFcm0v8WaF"
                }
            },
            "req_9": {
                "module": "vkey.GetVkeyServer",
                "method": "CgiGetVkey",
                "param": {
                    "guid": "6040093972",
                    "songmid": [
                        mid
                    ],
                    "songtype": [
                        0
                    ],
                    "uin": "1145087558",
                    "loginflag": 1,
                    "platform": "20",
                }
            }
        }
        file_name = item['file_name']
        if file_name != '':
            data["req_9"]["param"]["filename"] = [file_name]

        data_str = str(json.dumps(data, ensure_ascii=False, separators=(",", ":")))
        # print(data_str)
        sign = self.js.call('get_data', data_str)
        params = {
            "_": str(int(time.time() * 1000)),
            "sign": sign
        }
        # print(params)
        response = requests.post(url, headers=self.headers, params=params,
                                 data=data_str.encode())

        # print(response)
        res = response.json()
        # pprint.pprint(res)
        music_url = res['req_9']["data"]["midurlinfo"][0]["purl"]
        print(music_url)
        if music_url == "":
            print("没有版权的歌曲")
            return
        music_url = "https://ws6.stream.qqmusic.qq.com/" + music_url
        music_url_content = requests.get(music_url, headers=self.headers).content  # 将歌曲下载地址转化为二进制格式

        music_file_name = item['song_name'] + "---" + item['singer_name'] + ".mp3"  # 歌曲保存的名称  歌曲名+歌手名
        file_address = "./song/"

        try:
            if not os.path.exists(file_address):
                os.mkdir(file_address)
            if not os.path.exists(file_address + music_file_name):
                print("正在下载     %s" % music_file_name)
                with open(file_address + music_file_name, "wb") as f:  # 保存语句
                    f.write(music_url_content)
                print(music_file_name, "   下载成功")
            else:
                print(music_file_name, "   文件已存在")
        except:
            print("下载失败")


if __name__ == '__main__':
    m = Music()
    singer_name = ''
    page = 1
    song_num = ''
    while singer_name != 'q':
        if song_num != 'n':
            singer_name = input("请输入歌手名称(输入q退出): ")
            m.song_list = []
            page = 1
        if singer_name == 'q':
            break

        m.get_list(page, singer_name)
        song_num = input("请输入下载歌曲编号(输入n下一页): ")
        if song_num == 'n':
            page += 1
            continue
        item = m.song_list[int(song_num) - 1]
        m.down(item)
